<template>
    <div>
        <div>
            选择原始视频文件:
            <input type="file" @change="onFileChange" id="select_origin_file">
        </div>  
        <div>
            <button @click="startClip">开始剪辑视频</button>
            <button @click="attachWatermask">添加水印</button>
            <div>
                <span>用了几个在线图片，可以直接点合成</span>
                <button @click="compositeVideo">图片合成视频</button>
            </div>
            <h3>{{percentage}} %</h3>
        </div>   
        <div>
            <video :src="previewUrl" id="my-video" width="500"  controls></video>
        </div>
        <div>
            <h2>剪辑后的视频</h2>
            <video :src="clipedUrl" width="500" controls></video>
        </div>
    </div>
</template>

<script>

import FFmpeg from "@ffmpeg/ffmpeg";
const { createFFmpeg, fetchFile } = FFmpeg;
const ffmpeg = createFFmpeg({
    corePath: './ffmpeg-core.js',
    log: true,
});

export default {
    name: 'HelloWorld',
    created(){
        this.initFFmpeg();
    },
    data(){
        return {
            initFFmpegBool: false,
            previewUrl: '',
            clipedUrl: '',
            originFile: null,
            percentage: 0,
        }
    },
    methods:{
        async initFFmpeg() {
            const isLoaded = ffmpeg.isLoaded()
            if (!isLoaded) {
                await ffmpeg.load();
                console.log('ffmpeg 加载完毕！')
                this.initFFmpegBool = true;
                // 设置进度条
                ffmpeg.setProgress(({ ratio }) => {
                    console.log(ratio);
                    this.percentage = Math.floor(ratio * 100);
                });
            }
        },
        onFileChange(e){
            const file = e.target.files[0];
            this.originFile = file;
            this.previewUrl = window.webkitURL.createObjectURL(file)
        },
        async startClip(){
            const { name } = this.originFile;
            // 将视频加载到内存，注意fetchFile返回得是arrayBuffer
            ffmpeg.FS('writeFile', name, await fetchFile(this.originFile));
            // 注意格式 00:00:00
            const startTime = '00:00:00';
            const endTime = '00:00:10';
            await ffmpeg.run('-i', name, '-ss', startTime, '-to', endTime, 'output.mp4');
            const data = ffmpeg.FS('readFile', 'output.mp4');
            this.clipedUrl = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));
        },
        async attachWatermask(){
            const { name } = this.originFile;
            // 将视频加载到内存
            ffmpeg.FS('writeFile', name, await fetchFile(this.originFile));
            // 加载水印图片
            let watermask = 'watermask.png';
            ffmpeg.FS('writeFile', watermask, await fetchFile('https://upload.jianshu.io/users/upload_avatars/4509166/e8f1fe83-4203-472b-b29b-1d04842f0f7d.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/96/h/96/format/webp'));
            // -acodec copy：保持音频不变
            // -vf “…”：水印处理参数, watermask.png是水印图片;overlay=20:20是图片左上角距离视频左上角的距离。
            // 还可以修改水印图片的尺寸
            // await ffmpeg.run('-i', 'watermask.png', '-strict', '-2', '-s', '240x240', 'watermask1.png');
            // 添加文字水印，需要加载字体文件
            // ffmpeg.FS('writeFile', 'myfont.TTF', await fetchFile('./myfont.TTF'));
            // await ffmpeg.run('-i', name, '-vf', "drawtext=fontfile=myfont.TTF:text='1':x=300:y=500:fontsize=100:fontcolor=yellow:shadowy=2", 'output.mp4');
            // 更多请看：https://cloud.tencent.com/developer/article/1774971?from=15425
            await ffmpeg.run('-i', name, '-vf', "movie=watermask.png[watermark];[in][watermark]overlay=20:20", 'output.mp4');
            const data = ffmpeg.FS('readFile', 'output.mp4');
            this.clipedUrl = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));
        },
        async compositeVideo(){
            const imageList = [
                'https://img0.baidu.com/it/u=3967008561,1759248667&fm=253&fmt=auto&app=120&f=JPEG?w=1200&h=675',
                'https://img0.baidu.com/it/u=3396602011,1979079210&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=313',
                'https://img1.baidu.com/it/u=71885453,474453660&fm=253&fmt=auto&app=120&f=JPEG?w=1422&h=800',
                'https://img0.baidu.com/it/u=3222079260,4146877074&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500',
                'https://img2.baidu.com/it/u=3999091694,1705560228&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800',
                'https://img0.baidu.com/it/u=705102279,1721672537&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500'
            ]
            for (let i = 0; i < imageList.length; i++) {
                // 注意手动给成png格式会报错 Invalid PNG signature
			    ffmpeg.FS('writeFile', `image${i}.jpeg`, await fetchFile(imageList[i]));
			}

            ffmpeg.FS('writeFile', 'output.mp3', await fetchFile('output.mp3'));

            // -r调整帧率，默认25帧，也就是1秒钟拼接25张图片
            // -t 指定视频时长
            // -s 指定尺寸大小，必须
            // 也可以固定宽或者高等比例拉伸
            // -vf scale=-1:480  -1表示比例缩放，480 是固定高度
            // todo：同时添加音乐
            await ffmpeg.run('-r', '1', '-f', 'image2', '-i', 'image%d.jpeg', '-t', '5', '-s', '640x480', 'output1.mp4');
            await ffmpeg.run('-i', 'output1.mp4','-i', 'output.mp3', '-c', 'copy', '-map', '0:v:0', '-map', '1:a:0', 'output.mp4')
            const data = ffmpeg.FS('readFile', 'output.mp4');
            this.clipedUrl = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));

        },
        async addBgm(){
            ffmpeg.FS('writeFile', 'output.mp3', await fetchFile('output.mp3'));
        }
    },
    beforeDestroy(){
        ffmpeg.exit && ffmpeg.exit();
        ffmpeg = null;
    }
}
</script>
